import Constants from "../Constants/Constants";
import G from "../Utilities/Global";
import BattleScene from "../BattleScene";
import EntityTypes from "../Constants/EntityTypes";
import Monster from "../Entity/Monster";
import C from "../Configs/Config";
import EntityStruct from "../Entity/EntityStruct";
import MapAssetStruct from "../Structs/MapAssetStruct";
import MonsterAssetStruct from "../Structs/MonsterAssetStruct";
import Oriented from "../Constants/Oriented";

/**
 * 怪物ai控制器 
 * created by Five on 2018-11-13 15:13:21
 */
export default class MonsterController extends cc.Component {
    private _runningScene: BattleScene;

    public monsters: Array<Monster>;
    start() {
        this.Init();
    }

    public Init() {
        this.unscheduleAllCallbacks();

        // 将所有直接摆放的怪摆上来
        this.monsters = new Array<Monster>();
        this._runningScene = G().CurScene;
        this._runningScene.MapData.Monsters.forEach(mon => {
            this.createMonster(mon, mon.Asset);
        });

        // 怪物出生点按照时间间隔出怪
        let doors = this._runningScene.MapData.GetEntitiesByType(EntityTypes.MONSTERDOOR);
        doors.forEach((door) => {
            let asset = door.Asset as MapAssetStruct;
            this.schedule(() => {
                if (asset.id == 20019)
                    this.periodicBorn(door, Oriented.RIGHT);
                else
                    this.periodicBorn(door, Oriented.LEFT);
            }, 10)
        });
    }

    async createMonster(struct: EntityStruct, monster: MonsterAssetStruct) {
        let node = await G().Res.GetRes(Constants.PRE_MONSTER) as cc.Node;
        let anim = node.getChildByName("anim");
        let pos = G().Calc.LocationToPostion(struct.Location);
        anim.addComponent(cc.Sprite).sizeMode = cc.Sprite.SizeMode.CUSTOM;
        pos.addSelf(cc.v2(0, 0));
        node.position = pos;
        node.getComponent(Monster).SetData(monster);
        node.getComponent(Monster).SetAnim(anim);
        node.getComponent(Monster).Init();
        node.getComponent(Monster).SetNav();
        this._runningScene.EntityAttachPoint.addChild(node);
        this.monsters.push(node.getComponent(Monster));
    }

    private freeze: boolean = false;
    async periodicBorn(door: EntityStruct, ori: Oriented) {
        if (this.freeze)
            return;

        // 拿到要刷新的怪
        let asset = door.Asset as MapAssetStruct;
        let monster = C().Monster.Get(asset.dropdown);
        monster.oriented = ori;
        this.createMonster(door, monster);
    }

    public KillAll() {
        this.monsters.forEach((monster) => {
            if (monster.node != null)
                monster.die();
        });
        this.monsters.length = 0;
    }

    public ExistMonster(position: cc.Vec2) {
        let loc = G().Calc.PositionToLocation(position);
        for (let monster of this.monsters) {
            if (monster.node) {
                let mpos = monster.node.position;
                let ori = monster._oriented();
                let neighbor = ori == Oriented.LEFT ? Constants.ENTITY_EDGE / 2 : 60;
                let mloc = G().Calc.PositionToLocation(mpos);
                let nloc = G().Calc.PositionToLocation(mpos.add(cc.v2(neighbor, 0)));
                cc.log(nloc, mloc);
                if (loc == mloc || nloc == loc)
                    return true;
            }
        }
        return false;
    }

    /**
     * 静止所有怪物
     * @param n 时长
     */
    public TimeFreeze(n: number) {
        this.monsters.forEach((monster) => {
            if (monster.node)
                monster.Freeze();
        });
        this.freeze = true;
        // 定时解除
        this.scheduleOnce(this.TimeFlowing, n);
    }

    /**
     * 解除怪物静止
     */
    public TimeFlowing() {
        this.monsters.forEach((monster) => {
            if (monster.node)
                monster.UnFreeze();
        });
        this.freeze = false;
    }
}